#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <pthread.h>

#define BACKLOG 5

void SigHandle(int sig);
void *ClinetHandle(void* arg);

void SigHandle(int sig){
	if(sig == SIGCHLD){
		printf("client exited\n");
		wait(NULL);
	}
}
void *ClinetHandle(void* arg){
	int ret;
	char buf[BUFSIZ] = {};
	int newfd = *(int *)arg;
	while(1){
		//memset(buf, 0, BUFSIZ);
		bzero(buf, BUFSIZ);
		ret = read(newfd, buf, BUFSIZ);
		if(ret < 0){
			perror("read");
			exit(0);
		}else if(ret == 0)
			break;
		else
			printf("buf = %s\n", buf);
	}
	printf("client exited\n");
	close(newfd);
	return NULL;

}
int main(int argc, char *argv[]){//利用传参的方式来获取端口号和IP地址

	int sockfd;
	int newfd;
	int add;
	pthread_t tid;
	struct sockaddr_in addr, clint_addr;
	socklen_t addrlen = sizeof(clint_addr);

	struct sigaction act;
	act.sa_handler = SigHandle;
	act.sa_flags = SA_RESTART;
	sigemptyset(&act.sa_mask);
	sigaction(SIGCHLD, &act, NULL);

	if(argc < 3){
		fprintf(stderr, "%s<addr><port>\n", argv[0]);
		return 0;
	}

	if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
		perror("socket");
		return 0;
	}
	addr.sin_family = AF_INET;
	addr.sin_port = htons( atoi(argv[2]) );

	if((inet_aton(argv[1], &addr.sin_addr)) == 0){
		fprintf(stderr, "Invalid address\n");
		return 0;
	}

	int flag = 1, len = sizeof(int);
	int set;
	set = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &flag, len);
	if(set == -1){
		perror("setsockopt");
		exit(1);
	}//套接字设置 地址快速重用

	add = bind(sockfd, (struct sockaddr *)&addr, sizeof(addr));
	if(add == -1){
		perror("bind");
		return 0;
	}

	if((listen(sockfd, BACKLOG)) == -1){
		perror("listen");
		return(0);
	}

	while(1){
		// 接收新客户端的连接请求， 生成新的用于和客户端通信的套接字
		if((newfd = accept(sockfd, (struct sockaddr *)&clint_addr, &addrlen)) < 0){
			perror("accept");
			return 0;
		}

		printf("addr: %s port: %d\n", inet_ntoa(clint_addr.sin_addr), ntohs(clint_addr.sin_port));
		pthread_create(&tid, NULL, ClinetHandle, &newfd);
		pthread_detach(tid);
	}
	close(sockfd);

	return 0;
}
